<template>
  <q-tr ref="TableTD" :class="bodyRowCls" :props="props" @click.stop="handleClickRow('rowClick')"
        @dblclick.stop="handleClickRow('rowDbClick')">
    <q-td v-if="selection" class="qx-table--selection-td" @click.stop="" @dblclick.stop="">
      <slot :props="props" name="selection"></slot>
    </q-td>
    <q-td key="index" :class="bodyCellCls({})" :props="props" :style="{ left }" class="qx-table--index-td"
          @click.stop="handleClickRow('cellClick', {})" @dblclick.stop="handleClickRow('cellDbClick', {})">
      {{ props.rowIndex + 1 }}
    </q-td>
    <template v-for="column in leftCols" :key="column.name">
      <q-td :class="bodyCellCls(column)" :colspan="mergeSpan(column, 1)" :props="props" :rowspan="mergeSpan(column)"
            :style="fixedLeft(column)" @click.stop="handleClickRow('cellClick', column)"
            @dblclick.stop="handleClickRow('cellDbClick', column)">
        <template v-if="column.__has_child">
          <q-icon :name="props.expand ? 'keyboard_arrow_down' : 'keyboard_arrow_right'" :size="expandIconSize"
                  class="text-bold absolute expand-btn" @click.stop="toggleExpand(props)" />
        </template>
        <template v-if="column.slot">
          <slot :name="column.field"></slot>
        </template>
        <template v-else>
          <template v-if="column.useTag && !isEmpty(column.value)">
            <q-badge :color="getColor(column)" class="q-badge-dot absolute-badge-dot" rounded></q-badge>
            <div class="q-pl-md">{{ getLabel(column) }}</div>
          </template>
          <qx-tooltip v-else :rowsNum="column.rowsNum || 3">{{ getLabel(column) }}</qx-tooltip>
        </template>
      </q-td>
    </template>
    <template v-for="column in mainCols" :key="column.name">
      <q-td :class="bodyCellCls(column)" :colspan="mergeSpan(column, 1)" :props="props" :rowspan="mergeSpan(column)"
            :style="getTdPaddingLeft(column)" @click.stop="handleClickRow('cellClick', column)"
            @dblclick.stop="handleClickRow('cellDbClick', column)">
        <template v-if="column.__has_child">
          <q-icon :name="props.expand ? 'keyboard_arrow_down' : 'keyboard_arrow_right'" :size="expandIconSize"
                  class="text-bold absolute expand-btn" @click.stop="toggleExpand(props)" />
        </template>
        <template v-if="column.slot">
          <slot :name="column.field"></slot>
        </template>
        <template v-else>
          <template v-if="column.useTag && !isEmpty(column.value)">
            <q-badge :color="getColor(column)" class="q-badge-dot absolute-badge-dot" rounded></q-badge>
            <span class="q-ml-md">{{ getLabel(column) }}</span>
          </template>
          <qx-tooltip v-else :rowsNum="column.rowsNum || 3">{{ getLabel(column) }}</qx-tooltip>
        </template>
      </q-td>
    </template>
    <template v-for="column in rightCols" :key="column.name">
      <q-td :class="bodyCellCls(column)" :colspan="mergeSpan(column, 1)" :props="props" :rowspan="mergeSpan(column)"
            :style="fixedRight(column)" @click.stop="handleClickRow('cellClick', column)"
            @dblclick.stop="handleClickRow('cellDbClick', column)">
        <template v-if="column.__has_child">
          <q-icon :name="props.expand ? 'keyboard_arrow_down' : 'keyboard_arrow_right'" :size="expandIconSize"
                  class="text-bold absolute expand-btn" @click.stop="toggleExpand(props)" />
        </template>
        <template v-if="column.slot">
          <slot :name="column.field"></slot>
        </template>
        <template v-else>
          <template v-if="column.useTag && !isEmpty(column.value)">
            <q-badge :color="getColor(column)" class="q-badge-dot absolute-badge-dot" rounded></q-badge>
            <div class="q-ml-md">{{ getLabel(column) }}</div>
          </template>
          <qx-tooltip v-else :rowsNum="column.rowsNum || 3">{{ getLabel(column) }}</qx-tooltip>
        </template>
      </q-td>
    </template>
    <q-td key="menu" :class="bodyCellCls({})" :props="props" class="qx-table--menu-td" @click.stop="" @dblclick.stop="">
      <div class="row justify-center items-center q-gutter-sm">
        <slot name="menu"></slot>
      </div>
    </q-td>
  </q-tr>
</template>

<script setup>
import QxTooltip from 'components/Global/Tools/QxTooltip.vue'
import { getLabel, getResult } from 'components/tableUtils'
import { getColorByValue, isEmpty } from 'src/utils/utils'
import { computed, ref, watchEffect } from 'vue'

const prefix = 'qx-fixed-column-td-'

const prop = defineProps({
  props: Object, childKey: String, treeNode: String, selection: String, rowClick: Function, canExpand: Boolean,
  cellClick: Function, cellDbClick: Function, mergeCells: { type: Object, default: () => ({}) },
  dbRowClick: Function, rowCls: [String, Function]
})
const emits = defineEmits(['toggleExpand', 'dbRowClick'])
const fixedInfo = defineModel('fixedColsInfo', { type: Object, default: () => ({}) })

const leftCols = ref([])
const mainCols = ref([])
const rightCols = ref([])
const TableTD = ref(null)
const expandIconSize = ref('1.125rem')
const left = computed(() => prop.selection ? '2.25rem' : 0)
const childKey = computed(() => prop.childKey || 'children')
const fixedLeft = computed(() => (column = {}) => {
  const leftWidth = fixedInfo.value[column.name]
  if (leftWidth) return { left: `${leftWidth}px`, ...getTdPaddingLeft(column) }
})
const fixedRight = computed(() => (column = {}) => {
  const rightWidth = fixedInfo.value[column.name]
  if (rightWidth) return { right: `${rightWidth}px`, ...getTdPaddingLeft(column) }
})
const bodyRowCls = computed(() => {
  const { cellClick, cellDbClick, dbRowClick, props = {}, rowClick, rowCls } = prop
  const cls = `${props.rowIndex % 2 ? 'bg-even' : ''} ${getResult(rowCls, props)}`
  return rowClick || cellClick || cellDbClick || dbRowClick ? `${cls} cursor-pointer cursor-hover` : cls
})
const bodyCellCls = computed(() => (column = {}) => {
  let cls = 'relative-position '
  if (column.fixed) cls += `${prefix}${column.name} `
  if (column.__has_child) return cls + 'can-expand-cell cursor-pointer cursor-hover'
  return column.cellClick || column.cellDbClick ? cls + 'cursor-pointer text-primary cursor-hover' : cls
})

const mergeCell = column => prop.mergeCells[column.name] || [1, 1]
const mergeSpan = (column = {}, Num = 0) => mergeCell(column)[Num]
const toggleExpand = props => emits('toggleExpand', props, childKey.value)
const hasChild = (row = {}, column = {}) => {
  if (prop.canExpand && column.isExpand) return true
  return prop.treeNode && row[childKey.value]?.length ? column.field === prop.treeNode : false
}
const splitCols = () => {
  leftCols.value = []
  mainCols.value = []
  rightCols.value = []
  const { cols, row } = prop.props || {}
  for (const col of cols || []) {
    if (['index', 'menu'].includes(col.name) || (!mergeCell(col)[0] && !mergeCell(col)[1])) continue
    if (!col.fixed) mainCols.value.push({ ...col, __has_child: hasChild(row, col) })
    else if (col.fixed === 'left') leftCols.value.push({ ...col, __has_child: hasChild(row, col) })
    else if (col.fixed === 'right') rightCols.value.push({ ...col, __has_child: hasChild(row, col) })
  }
}
const getColor = ({ tagColors, value, options = [], props: rowProps }) => {
  return tagColors ? tagColors[value] || 'primary' : getColorByValue(value, options, rowProps, 'primary')
}
const getTdPaddingLeft = column => {
  const { props = {}, treeNode = '' } = prop, { row = {} } = props
  if (!treeNode || column.field !== prop.treeNode) return {}
  const PL = row[childKey.value]?.length ? 0 : 16
  return { 'padding-left': `calc(${expandIconSize.value} + ${Number(row.level || 0) * 10 + PL}px)` }
}
const handleClickRow = (action, column = {}) => {
  const { cellClick, cellDbClick, dbRowClick, props = {}, rowClick } = prop, { colsMap, row, rowIndex = 0 } = props
  if (action === 'rowClick') return rowClick && rowClick(row, column, colsMap, rowIndex)
  if (action === 'rowDbClick') return dbRowClick && dbRowClick(row, column, colsMap, rowIndex)
  if (action === 'cellClick') {
    if (column.__has_child) return toggleExpand(props)
    if (column.cellClick) return column.cellClick(row, column, rowIndex)
    if (cellClick) return cellClick(row, column, rowIndex)
    if (rowClick) return rowClick(row, column, colsMap, rowIndex)
  }
  if (action === 'cellDbClick') {
    if (column.cellDbClick) return column.cellDbClick(row, column, rowIndex)
    if (cellDbClick) return cellDbClick(row, column, rowIndex)
    if (dbRowClick) return dbRowClick(row, column, colsMap, rowIndex)
  }
}

watchEffect(splitCols)
</script>

<style lang="scss">
.can-expand-cell {
  padding-left: v-bind(expandIconSize) !important;
}
</style>